package me.zhengjie.utils.map;


import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.domain.AreaConf;
import me.zhengjie.utils.IntegerUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

/**
 * 高德API工具类
 */
@Slf4j
public class GaodeMapUtils {


    //高德接口主域名
    private static final String url_domain = "https://restapi.amap.com";
    //高德接口API Key
    private static final String api_key = "c2c60764102dcb1de5976e2e0eab97ce";
    //地理位置编码接口
    private static final String uri_search_location = "/v3/geocode/geo";
    //驾车路径规划2.0接口
    private static final String uri_route_plan = "/v5/direction/driving";

    /**
     * 高德驾车路径规划
     *  (起始和目的地传入火星坐标系)
     * @param originLng 起始经度
     * @param originLat 起始纬度
     * @param destLng 目的地经度
     * @param destLat 目的地纬度
     * @return 规划路径的折线坐标 (地球坐标系)
     */
    public static List<BigDecimal[]> routePlan(String originLng, String originLat, String destLng, String destLat) {

        String origin = originLng + "," + originLat;
        String destination = destLng + "," + destLat;
        RestTemplate restTemplate = new RestTemplate();
        //填入请求参数
        String urlForGet = url_domain + uri_route_plan + "?" +
                "key=" + api_key +
                "&origin=" + origin +
                "&destination=" + destination +
                "&strategy=35,0,37" +//速度优先
                "&show_fields=polyline";
        log.info("请求路径规划，参数：" + urlForGet);
        ResponseEntity<String> forEntity = restTemplate.getForEntity(urlForGet, String.class);
        List<BigDecimal[]> result = new ArrayList<>();
        if (!Integer.valueOf(200).equals(forEntity.getStatusCodeValue())) {
            log.error("路径规划失败,错误代码：" + forEntity.getStatusCodeValue() + ",错误信息：" + forEntity.getBody());
            return result;
        }
        String body = forEntity.getBody();
        JSONObject res = JSONObject.parseObject(body, JSONObject.class);
        if (res != null && StringUtils.equals("1", res.getString("status"))) {
            //表示查询结果正常了，接下来做处理
            if (IntegerUtil.valueOf(res.getString("count"), 0) < 1) {
                log.info("未找到路径规划");
                return result;
            }

            //表述搜索到了确切的路径
            String route = res.getString("route");
            JSONObject routeArray = JSONObject.parseObject(route, JSONObject.class);
            List<BigDecimal[]> linePoint = new ArrayList<>();
            String paths = routeArray.getString("paths");
            List<JSONObject> pathArray = JSONArray.parseArray(paths, JSONObject.class);
            JSONObject jsonPath = pathArray.get(0);
            String steps = jsonPath.getString("steps");
            List<JSONObject> stepsArray = JSONArray.parseArray(steps, JSONObject.class);
            for (JSONObject ele : stepsArray) {
                String polylineStr = ele.getString("polyline");
                String[] split = polylineStr.split(";");
                for (String str : split) {
                    String[] position = str.split(",");
                    linePoint.add(new BigDecimal[]{new BigDecimal(position[0]), new BigDecimal(position[1])});
                }
            }
//            log.info("当前路径坐标{}", linePoint);
            linePoint.forEach(ele -> {
                double[] doubles = LonlatConver.gcj02_To_Wgs84(ele[0].doubleValue(), ele[1].doubleValue());
                result.add(new BigDecimal[]{new BigDecimal(String.valueOf(doubles[0])), new BigDecimal(String.valueOf(doubles[1]))});
            });
            log.info("请求路径规划成功，该路径共包含{}个坐标点", linePoint.size());
        }

        return result;
    }

    /**
     * 高德搜索具体地点
     *
     * @param city 所在城市
     * @param address 搜索的地名
     * @return 具体地点的位置信息，包含地名、所在城市区域、经纬度（GPS坐标系）等
     */
    public static AreaConf searchLocation(String city, String address) {

        RestTemplate restTemplate = new RestTemplate();
        //填入请求参数
        String urlForGet = url_domain + uri_search_location + "?" +
                "key=" + api_key +
                "&city=" + city +
                "&address=" + address;
        log.info("请求搜索具体地理编码，参数：" + urlForGet);
        ResponseEntity<String> forEntity = restTemplate.getForEntity(urlForGet, String.class);

        if (!Integer.valueOf(200).equals(forEntity.getStatusCodeValue())) {
            log.error("搜索具体地理编码,错误代码：" + forEntity.getStatusCodeValue() + ",错误信息：" + forEntity.getBody());
            return null;
        }
        String body = forEntity.getBody();
        JSONObject res = JSONObject.parseObject(body, JSONObject.class);
        if (res != null && StringUtils.equals("1", res.getString("status"))) {
            //表示查询结果正常了，接下来做处理
            if (IntegerUtil.valueOf(res.getString("count"), 0) < 1) {
                return null;
            }
            //表述这有确切的地点
            String route = res.getString("geocodes");
            if (StringUtils.isBlank(route)) {
                return null;
            }
            List<JSONObject> routeArray = JSONObject.parseArray(route, JSONObject.class);
            JSONObject jsonPath = routeArray.get(0);
            String locationGcj02 = jsonPath.getString("location");
            if (StringUtils.isBlank(locationGcj02)) {
                return null;
            }
            AreaConf result = new AreaConf();
            result.setGisAreaName(jsonPath.getString("formatted_address"));
            result.setCity(jsonPath.getString("city"));
            result.setCityCode(jsonPath.getString("citycode"));
            result.setDistrict(jsonPath.getString("district"));
            result.setDistrictCode(jsonPath.getString("adcode"));
            result.setProvince(jsonPath.getString("province"));
            result.setPositionGcj02(locationGcj02);
            String[] locationSplits = locationGcj02.split(",");
            double[] doubles = LonlatConver.gcj02_To_Wgs84(Double.parseDouble(locationSplits[0]), Double.parseDouble(locationSplits[1]));
            result.setPosition(doubles[0] + "," + doubles[1]);
            return result;
        }

        return null;
    }
}
